﻿using System;
using System.Linq;
using System.Collections.Generic;

namespace JellystonePark.Model
{
    /// <summary>
    /// Játéktábla típusa.
    /// </summary>
    public class JellystoneTable
    {
        public enum JellystoneField { Blank, Yogi, Basket, Tree, RangerVU, RangerHR, RangerVD, RangerHL }

        #region Fields

        private List<List<JellystoneField>> _fields;

        #endregion

        #region Properties

        /// <summary>
        /// Játéktábla oldalhossza.
        /// </summary>
        public Int32 SideLength { get { return _fields.Capacity; } }
        
        /// <summary>
        /// Adott indexen szereplő érték lekérdezése
        /// </summary>
        /// <param name="x">Vízszintes koordináta</param>
        /// <param name="y">Függőleges koordináta</param>
        /// <returns>Érték mező típusú.</returns>
        public JellystoneField this[int x, int y] { get { return GetValue(x, y); } set { SetValue(x, y, value); } }
                
        /// <summary>
        /// Maci Laci aktuális helyzete
        /// </summary>
        public Tuple<int, int> YogyCurrentPos
        {
            get
            {
                for (int i = 0; i < _fields.Count; ++i)
                    for (int j = 0; j < _fields[i].Count; ++j)
                        if (JellystoneField.Yogi == _fields[i][j])
                            return Tuple.Create<int, int>(i, j);

                return Tuple.Create<int, int>(-1, -1);
            }
        }
        /// <summary>
        /// A táblán található kosarak megszámlálása.
        /// </summary>
        public int CountBaskets
        {
            get
            {
                int c = 0;
                for (int i = 0; i < SideLength; ++i)
                    for (int j = 0; j < SideLength; ++j)
                        if (JellystoneField.Basket == _fields[i][j])
                            ++c;

                return c;
            }
        }

        #endregion

        #region Constructors

        public JellystoneTable() : this(10) { }

        /// <summary>
        /// Játéktábla példányosítása.
        /// </summary>
        /// <param name="n">Oldalhossz (db elem)</param>
        public JellystoneTable(int n)
        {
            if (n < 0)
                throw new ArgumentOutOfRangeException("The table size is less than 0.", "n");            

            _fields = new List<List <JellystoneField>>(n);
            for (int i = 0; i < _fields.Capacity; ++i)
            {
                _fields.Add(new List<JellystoneField>());
                _fields[i].Capacity = n;
                for (int j = 0; j < _fields[i].Capacity; ++j)
                    _fields[i].Add(JellystoneField.Blank);
            }
        }

        /// <summary>
        /// Játéktábla példányosítása táblával.
        /// </summary>
        /// <param name="table"></param>
        public JellystoneTable(JellystoneTable table)
        {
            _fields = new List<List<JellystoneField>>(table.SideLength);
            for (int i = 0; i < _fields.Capacity; ++i)
            {
                _fields.Add(new List<JellystoneField>(table.SideLength));
                for (int j = 0; j < _fields[i].Capacity; ++j)
                    _fields[i].Add(table[i, j]);
            }

        }

        #endregion

        #region Public methods
        
        /// <summary>
        /// Adott helyen szereplő érték lekérdezése.
        /// </summary>
        /// <param name="x">Vízszintes koordináta</param>
        /// <param name="y">Függőleges koordináta</param>
        /// <returns>Mező értéke</returns>
        public JellystoneField GetValue(int x, int y)
        {
            if (x >= 0 && x < _fields.Count && y >= 0 && y < _fields[x].Count)
                return _fields[x][y];
            return JellystoneField.Blank;
        }

        /// <summary>
        /// Ellenőrzés után beállítja egy mező értékét a játéktáblán.
        /// </summary>
        /// <param name="x">Vízszintes koordináta</param>
        /// <param name="y">Függőleges koordináta</param>
        /// <param name="v">Érték</param>
        /// <returns>Igaz, ha érvényesek a koordináták és a paraméter beilleszthető oda.</returns>
        public bool SetValue(int x, int y, JellystoneField v)
        {
            if (x < 0 || x >= _fields.Capacity)
                return false;
            if (y < 0 || y >= _fields[x].Capacity)
                return false;

            switch (v)
            {
                case JellystoneField.Yogi:
                    if (JellystoneField.Blank == _fields[x][y] || JellystoneField.Basket == _fields[x][y])
                        _fields[x][y] = v;
                    else
                        return false;
                    break;
                case JellystoneField.RangerHL:
                case JellystoneField.RangerHR:
                case JellystoneField.RangerVD:
                case JellystoneField.RangerVU:
                    if (JellystoneField.Blank == _fields[x][y])
                        _fields[x][y] = v;
                    else
                        return false;
                    break;
                default:
                    _fields[x][y] = v;
                    break;
            }

            return true;
        }

        #endregion
    }
}
